#pragma once

#include <stm32f10x_usart.h>

#include "share/cccompat.h"
#include "mcu.h"

#ifdef __cplusplus
extern "C" {
#endif

/// @brief UART 驱动数据结构
typedef struct _mcu_uart {
	/// UART 硬件设备
    USART_TypeDef* port;
    /// 接收数据中断处理接口
    func_uart_rxbyte_t rxhandler; void* rxcookie;
    /// 发送完成中断处理接口
    func_uart_txempty_t txhandler; void* txcookie;
} mcu_uart_t;

/// @brief 串口初始化
/// @param baudrate 波特率
/// @param databits 数据位
/// @param stopbits 停止位
/// @param parity 奇偶校验位
std_err_t mcu_uart_init(mcu_uart_t *dev, mcu_gpio_num_t txpin, mcu_gpio_num_t rxpin, uint32_t baudrate, mcu_uart_databits_t databits, mcu_uart_stopbits_t stopbits, mcu_uart_parity_t parity);

/// @brief 获取串口中断号
IRQn_Type mcu_uart_irqn(mcu_uart_t *dev);
/// @brief 串口中断处理函数
void mcu_uart_irq_handler(mcu_uart_t *dev);

/// @brief 串口 transceiver 实现函数
static inline size_t    _utrx_get_mtu(struct _transceiver* ifdev) { return 4096; }
static inline std_err_t _utrx_clear_rx_buffer(struct _transceiver *ifdev) { return STD_ERR_OK; } // STM32F4 USART 没有 FIFO
static inline rx_ret_t  _utrx_rx(struct _transceiver *ifdev, void* buf, size_t size, size_t *len, long timeout, long interval, const char *okFlag, rx_flag_t okFlagType, const char *failFlag, rx_flag_t failFlagType) { return mcu_uart_receive((mcu_uart_t*)ifdev->hif, buf, size, len, timeout, interval, okFlag, okFlagType, failFlag, failFlagType); }
static inline std_err_t _utrx_rxline(struct _transceiver *ifdev, void* buf, size_t size, size_t *len) { return mcu_uart_receive((mcu_uart_t*)ifdev->hif, buf, size, len, 0, 0, "\n", RX_FLAG_STRING, NULL, RX_FLAG_NULL); }
static inline std_err_t _utrx_tx(struct _transceiver *ifdev, const void* buf, size_t size, size_t *len) { return mcu_uart_send((mcu_uart_t*)ifdev->hif, buf, size, len); }
static inline void      _utrx_close(struct _transceiver *ifdev) {} // { LL_USART_Disable(((mcu_uart_t*)ifdev->hif)->port); } // 硬件设备，无需关闭 ?

/// @brief 定义命名的 UART APIs
#define UART_DEFINE(NAME, PORT, TXPIN, RXPIN) \
	mcu_uart_t     _UART_##NAME = {PORT, NULL, NULL, NULL, NULL}; \
	mcu_uart_t*    UART_##NAME = &_UART_##NAME; \
	_RAMCODE_ void PORT##_IRQHandler(void) { mcu_uart_irq_handler(UART_##NAME); } \
	std_err_t      UART_##NAME##_Init(uint32_t baudrate, mcu_uart_databits_t databits, mcu_uart_stopbits_t stopbits, mcu_uart_parity_t parity) { return mcu_uart_init(UART_##NAME, MCU_GPIO_NUM_##TXPIN, MCU_GPIO_NUM_##RXPIN, baudrate, databits, stopbits, parity); } \
	transceiver_t  _##NAME##_TRX = { .hif = &_UART_##NAME, .get_mtu = _utrx_get_mtu, .clear_rx_buffer = _utrx_clear_rx_buffer, .rx = _utrx_rx, .rxline = _utrx_rxline, .tx = _utrx_tx, .close = _utrx_close, .on_rx_data = NULL, .on_tx_empty = NULL, .regexp_match = NULL, .ref_count = 0}; \
	transceiver_t* NAME##_TRX = &_##NAME##_TRX;
	
#ifdef __cplusplus
}
#endif
